package rexsee.core.browser;

import rexsee.core.browser.clazz.ExtensionListener;
import rexsee.core.browser.clazz.FilterListener;
import rexsee.core.browser.clazz.HistoryItem;
import rexsee.core.browser.clazz.JavascriptInterface;
import rexsee.core.lang.RexseeLanguage;
import rexsee.core.utilities.Utilities;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.webkit.WebBackForwardList;
import android.webkit.WebHistoryItem;
import android.widget.Toast;

public class RexseeBrowser implements JavascriptInterface {

	public static final String PARENT_INTERFACE_NAME = "Parent";
	public static final String INTERFACE_NAME = "Browser";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return childBrowser.function;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseeBrowser(childBrowser);
	}

	public String getParentInterfaceName() {
		return mBrowser.application.resources.prefix + PARENT_INTERFACE_NAME;
	}

	public boolean confirmOnQuit = true;
	private final Context mContext;
	private final Browser mBrowser;
	private OnJavascriptCallback onJavascriptCallback = null;

	public static abstract class OnJavascriptCallback {
		public abstract void onCallback(String text);
	}

	public RexseeBrowser(Browser browser) {
		super();
		mBrowser = browser;
		mContext = browser.getContext();
	}

	public void setCallback(OnJavascriptCallback callback) {
		onJavascriptCallback = callback;
	}
	public void clearCallback() {
		onJavascriptCallback = null;
	}

	//Callback
	public void callback(String text) {
		if (onJavascriptCallback != null) {
			OnJavascriptCallback callback = onJavascriptCallback;
			onJavascriptCallback = null;
			callback.onCallback(text);
		}
	}

	// Navigate
	public void load(String url) {
		try {
			mBrowser.urlListeners.run(url, true);
		} catch (Exception e) {
			mBrowser.exception(getInterfaceName(), e);
		}
	}
	public void loadFromCache(String url) {
		int oSteps = 0;
		if (mBrowser.history.getSize() != 0) {
			for (int i = (mBrowser.history.getSize() - 1); i >= 0; i--) {
				if (i != mBrowser.history.getCurrentIndex() && mBrowser.history.getItemAtIndex(i).getUrl().compareTo(url) == 0) {
					oSteps = i - mBrowser.history.getCurrentIndex();
					break;
				}
			}
		}
		if (oSteps != 0) {
			goBackOrForward(oSteps);
		} else {
			load(url);
		}
	}
	public void reload() {
		String url = mBrowser.history.getCurrentItem().getUrl();
		if (url.toLowerCase().startsWith("http://") || url.toLowerCase().startsWith("https://")) {
			FilterListener filterListener = mBrowser.urlListeners.getFilterByUrl(url);
			ExtensionListener extensionListener = mBrowser.urlListeners.getExtensionByUrl(url);
			if (filterListener == null && (extensionListener == null || !extensionListener.shouldProcessOnline())) {
				mBrowser.reload();
			} else {
				mBrowser.urlListeners.run(url, false);
			}
		} else {
			mBrowser.urlListeners.run(url, false);
		}
	}
	public void goBack() {
		if (mBrowser.parentBrowser != null && mBrowser.parentBrowser.menu.isOptionsMenuOpen) {
			((Activity) mContext).closeOptionsMenu();
		} else {
			goBackOrForward(-1);
		}
	}
	public void goForward() {
		goBackOrForward(1);
	}
	public void goBackOrForward(int steps) {
		goBackOrForward(steps, true);
	}
	public void goBackOrForward(int steps, boolean quit) {
		int newIndex = mBrowser.history.getCurrentIndex() + steps;
		if (newIndex < 0) {
			if (quit) {
				if (mBrowser.parentDialog == null) {
					if (confirmOnQuit) mBrowser.application.confirmQuit();
					else mBrowser.application.quit();
				} else {
					if (mBrowser.parentDialog.isCancelable()) {
						mBrowser.parentDialog.doCancel();
					}
				}
			}
			return;
		}
		if (newIndex > mBrowser.history.getSize() - 1) { return; }
		mBrowser.history.setCurrentIndex(newIndex);
		String url = mBrowser.history.getCurrentItem().getUrl();
		String scheme = Uri.parse(url).getScheme();
		FilterListener listener = mBrowser.urlListeners.getFilterByUrl(url);
		if (scheme != null && (scheme.compareTo("http") == 0 || scheme.compareTo("https") == 0) && listener == null) {
			WebBackForwardList originalHistory = mBrowser.copyBackForwardList();
			int oIndex = originalHistory.getCurrentIndex();
			int oSteps = 0;
			for (int i = originalHistory.getSize() - 1; i >= 0; i--) {
				if (i != oIndex && originalHistory.getItemAtIndex(i).getUrl().compareTo(url) == 0) {
					oSteps = i - originalHistory.getCurrentIndex();
					break;
				}
			}
			if (oSteps != 0) {
				mBrowser.pageBeforeStartListeners.run(mBrowser, url);
				mBrowser.goBackOrForward(oSteps);
			} else {
				mBrowser.urlListeners.run(url, false);
			}
		} else {
			mBrowser.urlListeners.run(url, false);
		}
	}
	public void go(String url) {
		load(url);
	}
	public void open(String url) {
		if (url.compareTo("") == 0) return;
		String scheme = Uri.parse(url).getScheme();
		if (scheme == null) {
			mBrowser.exception(getInterfaceName(), "Invalid URL: " + url);
			return;
		}
		if (scheme.compareTo("http") == 0 || scheme.compareTo("https") == 0) {
			Intent i = new Intent();
			i.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			i.setAction(Intent.ACTION_VIEW);
			i.setData(Uri.parse(url));
			mContext.startActivity(i);
		} else if (scheme.compareTo("file") == 0) {
			Intent i = new Intent();
			i.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			i.setAction(Intent.ACTION_VIEW);
			i.setDataAndType(Uri.parse(url), Utilities.getMime(url));
			mContext.startActivity(i);
		} else {
			load(url);
		}
	}
	public void stop() {
		Toast.makeText(mContext, RexseeLanguage.PROGRESS_STOP, Toast.LENGTH_SHORT).show();
		mBrowser.stopListeners.run(mContext, mBrowser, mBrowser.history.getCurrentItem().getUrl());
		mBrowser.stopLoading();
	}
	// Load HTML
	public void loadHTML(String html) {
		String url = mBrowser.application.resources.prefix + ":html?id=" + System.currentTimeMillis();
		mBrowser.history.add(url);
		mBrowser.loadDataWithBaseURL(null, html, "text/html", "utf-8", url);
		//mBrowser.loadDataWithBaseURL(null, html, "text/html", mBrowser.application.getDefaultEncoding(), url);
	}
	public void loadHTMLWithoutHistory(String html) {
		String url = mBrowser.application.resources.prefix + ":html?id=" + System.currentTimeMillis();
		mBrowser.loadDataWithBaseURL(null, html, "text/html", "utf-8", url);
		//mBrowser.loadDataWithBaseURL(null, html, "text/html", mBrowser.application.getDefaultEncoding(), url);
	}
	public void show(String title, String message) {
		String html = "";
		html += "<html><head><title>" + title + "</title></head><body>";
		html += "<div style='font-size:16px;padding:10px;background-color:#e7e7e7;border:1px solid #7f9db9;'>";
		html += "<div style='font-size:24px;font-family:arial;font-weight:bold;'>" + title + "</div>";
		html += "<hr><div style='line-height:150%;'>" + message + "</div><hr>";
		html += "<a href='" + mBrowser.application.resources.prefix + ":back' style='font-size:20px;'>" + RexseeLanguage.ACTION_BACK + "</a>";
		html += "&nbsp;|&nbsp;";
		html += "<a href='" + mBrowser.application.resources.prefix + ":quit' style='font-size:20px;'>" + RexseeLanguage.ACTION_QUIT + "</a>";
		html += "</div>";
		html += "</body></html>";
		loadHTML(html);
	}
	public void showWithoutHistory(String title, String message) {
		String html = "";
		html += "<html><head><title>" + title + "</title></head><body>";
		html += "<div style='font-size:16px;padding:10px;background-color:#e7e7e7;border:1px solid #7f9db9;'>";
		html += "<div style='font-size:24px;font-family:arial;font-weight:bold;'>" + title + "</div>";
		html += "<hr><div style='line-height:150%;'>" + message + "</div><hr>";
		html += "<a href='" + mBrowser.application.resources.prefix + ":back' style='font-size:20px;'>" + RexseeLanguage.ACTION_BACK + "</a>";
		html += "&nbsp;|&nbsp;";
		html += "<a href='" + mBrowser.application.resources.prefix + ":quit' style='font-size:20px;'>" + RexseeLanguage.ACTION_QUIT + "</a>";
		html += "</div>";
		html += "</body></html>";
		loadHTMLWithoutHistory(html);
	}

	//Others
	public void pauseTimers() {
		mBrowser.pauseTimers();
	}
	public void resumeTimers() {
		mBrowser.resumeTimers();
	}
	public void setAllowErrorDialog(boolean allow) {
		mBrowser.allowErrorDialog = allow;
	}
	public void setAllowScrollEvent(boolean allow) {
		mBrowser.allowScrollEvent = allow;
	}
	public boolean isAllowErrorDialog() {
		return mBrowser.allowErrorDialog;
	}
	public void clearCache() {
		mBrowser.clearCache(true);
	}
	public void clearFormData() {
		mBrowser.clearFormData();
	}
	public void setSaveFormData(boolean save) {
		mBrowser.getSettings().setSaveFormData(save);
	}

	public void clearHistory() {
		mBrowser.clearHistory();
		mBrowser.history.clear();
	}
	public String getHistory() {
		HistoryItem item;
		String rtn = "";
		rtn += "[";
		for (int i = 0; i < mBrowser.history.getSize(); i++) {
			if (i != 0) rtn += ",";
			item = mBrowser.history.getItemAtIndex(i);
			rtn += "{";
			rtn += "\"title\":\"" + item.getTitle() + "\",";
			rtn += "\"url\":\"" + item.getUrl() + "\"";
			rtn += "}";
		}
		rtn += "]";
		return rtn;
	}
	public int getTotalPages() {
		return mBrowser.history.getTotalPages();
	}
	public String getOriginalHistory() {
		WebBackForwardList history = mBrowser.copyBackForwardList();
		WebHistoryItem item;
		String rtn = "";
		rtn += "[";
		for (int i = 0; i < history.getSize(); i++) {
			if (i != 0) rtn += ",";
			item = history.getItemAtIndex(i);
			rtn += "{";
			rtn += "\"title\":\"" + item.getTitle() + "\",";
			rtn += "\"url\":\"" + item.getUrl() + "\"";
			rtn += "}";
		}
		rtn += "]";
		return rtn;
	}
	public void zoomIn() {
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mBrowser.zoomIn();
			}
		});
	}
	public void zoomOut() {
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mBrowser.zoomOut();
			}
		});
	}
	public float getCurrentZoom() {
		return mBrowser.getScale();
	}
	public void setFocusable(final boolean focusable) {
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (focusable) {
					mBrowser.setFocusable(true);
					mBrowser.setFocusableInTouchMode(true);
					mBrowser.requestFocus();
				} else {
					mBrowser.setFocusable(false);
				}
			}
		});
	}

	//Popup Window
	public String getDialogId() {
		if (mBrowser.parentDialog == null) return "";
		String id = mBrowser.parentDialog.getParentId();
		return (id == null) ? "" : id;
	}
	public void dismiss() {
		if (mBrowser.parentDialog != null) mBrowser.parentDialog.doCancel();
	}

	//Scrollbar
	public void enableScrollbar(boolean enable) {
		mBrowser.setHorizontalScrollBarEnabled(enable);
		mBrowser.setVerticalScrollBarEnabled(enable);
	}

	public boolean prepareFlash() {
		int i = 0;
		do {
			int j = mBrowser.getChildCount();
			if (i >= j) { return false; }
			if (mBrowser.getChildAt(i).getClass().getName().equalsIgnoreCase("com.adobe.flashplayer.FlashPaintSurface")) {
				SurfaceView flashSurface = (SurfaceView) mBrowser.getChildAt(i);
				flashSurface.setZOrderMediaOverlay(false);
				return true;
			}
			i++;
		} while (true);

	}
	public void keyDown(final int keyCode) {
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					mBrowser.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
				} catch (Exception e) {
					mBrowser.exception(getInterfaceName(), e);
				}
			}
		});
	}
	public void keyUp(final int keyCode) {
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					mBrowser.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
				} catch (Exception e) {
					mBrowser.exception(getInterfaceName(), e);
				}
			}
		});
	}

	public void setSource(String source) {
		mBrowser.source = source;
	}

}
